package com.mk.es.service.transport.pool;

import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.elasticsearch.client.transport.TransportClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * EsTransportClient对象池
 */
@Component("esTransportClientPool")
public class EsTransportClientPool {
    Logger logger = LoggerFactory.getLogger(EsTransportClientPool.class);

    /**
     * es连接对象池
     */
    private GenericObjectPool<TransportClient> transportClientPool = null;

    //#连接池中最少空闲的连接数,默认为0
    @Value("${es.client.pool.minIdle}")
    private Integer esClientPoolMinIdle;

    //#连接池中最大空闲的连接数,默认为8
    @Value("${es.client.pool.maxIdle}")
    private Integer esClientPoolMaxIdle;

    //#链接池中最大连接数，默认值8
    @Value("${es.client.pool.maxTotal}")
    private Integer esClientPoolMaxTotal;

    /**
     * elasticsearch集群名称
     */
    @Value("${es.cluster.name}")
    private String esClusterName;

    @Value("${es.client.transport.sniff}")
    private Boolean esClientTransportSniff;

    /**
     * elasticsearch服务器地址，多个,隔开
     */
    @Value("${es.cluster.hosts}")
    private String esClusterHosts;

    /**
     * 初始化EsTransportClient对象池
     */
    @PostConstruct
    private void init() {
        logger.debug("elasticsearch transport client object pool init()");

        //资源池配置
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
        poolConfig.setLifo(false); //改为先进先出

        //连接池中最少空闲的连接数,默认为0
        if (this.esClientPoolMinIdle != null) {
            poolConfig.setMinIdle(this.esClientPoolMinIdle);
        }
        //连接池中最大空闲的连接数,默认为8
        if (this.esClientPoolMaxIdle != null) {
            poolConfig.setMaxIdle(this.esClientPoolMaxIdle);
        }
        //链接池中最大连接数，默认值8
        if (this.esClientPoolMaxTotal != null) {
            poolConfig.setMaxTotal(this.esClientPoolMaxTotal);
        }

        //工厂
        EsTransportClientFactory factory = new EsTransportClientFactory(esClusterName, esClientTransportSniff, esClusterHosts);

        //创建资源池
        this.transportClientPool = new GenericObjectPool<TransportClient>(factory, poolConfig);
    }

    /**
     * 获取TransportClient对象
     *
     * @return
     * @throws Exception
     */
    public TransportClient getClient() throws Exception {
        TransportClient transportClient = this.transportClientPool.borrowObject();
        logger.debug("elasticsearch transport client object pool invoke getClient(), info: {}", transportClient);
        return transportClient;
    }

    /**
     * 释放TransportClient对象
     *
     * @param transportClient
     */
    public void releaseClient(TransportClient transportClient) {
        logger.debug("elasticsearch transport client object pool invoke releaseClient(), info: {}", transportClient);
        if (transportClient != null) {
            this.transportClientPool.returnObject(transportClient);
        }
    }

    /**
     * 关闭EsTransportClient对象池
     */
    @PreDestroy
    public void destroy() {
        logger.debug("elasticsearch transport client object pool invoke destroy()");

        if (this.transportClientPool != null) {
            this.transportClientPool.close();
        }
    }

}
